package com.liner.service.impl;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.liner.entity.ProductCategory;
import com.liner.entity.ProductInfo;
import com.liner.enums.ResponseEnum;
import com.liner.exception.ShopException;
import com.liner.mapper.ProductCategoryMapper;
import com.liner.mapper.ProductInfoMapper;
import com.liner.service.ProductInfoService;
import com.liner.vo.ProductExcelVo;
import com.liner.vo.SellerProductInfoListVo;
import com.liner.vo.SellerProductInfoMapVo;
import com.liner.vo.SellerProductInfoVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.InputStream;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.locks.ReentrantLock;

/**
 * <p>
 * 商品表 服务实现类
 * </p>
 *
 * @author liner
 * @since 2022-12-03
 */
@Service
@Slf4j
public class ProductInfoServiceImpl extends ServiceImpl<ProductInfoMapper, ProductInfo> implements ProductInfoService {

    @Autowired
    private ProductInfoMapper productInfoMapper;

    @Autowired
    private ProductCategoryMapper productCategoryMapper;

    private final ReentrantLock reentrantLock = new ReentrantLock();

    @Override
    public BigDecimal findPriceById(Integer id) {
        return productInfoMapper.findPriceById(id);
    }

    @Override
    public Boolean subStockById(Integer id, Integer quantity) {
        //判断库存
        Integer stock = productInfoMapper.findStockById(id);
        if (quantity > stock) {
            //抛出异常
            throw new ShopException(ResponseEnum.STOCK_ERROR.getMsg());
        }
        //减少库存
        reentrantLock.lock();
        int result = stock - quantity;
        productInfoMapper.updateStock(id, result);
        reentrantLock.unlock();
        return true;
    }

    @Override
    public Boolean addStockById(Integer id, Integer quantity) {

        productInfoMapper.insertStock(id, quantity);
        return true;
    }

    @Override
    @Transactional
    public SellerProductInfoListVo sellerProductInfoVo(Integer page, Integer size) {
        Page<ProductInfo> infoPage = new Page<>(page, size);
        Page<ProductInfo> productInfoPage = productInfoMapper.selectPage(infoPage, null);
        return getSellerProductInfoListVo(productInfoPage);
    }

    @Override
    @Transactional
    public SellerProductInfoListVo sellerProductInfoVoLike(String keyWord, Integer page, Integer size) {
        Page<ProductInfo> infoPage = new Page<>(page, size);
        LambdaQueryWrapper<ProductInfo> queryWrapper = new LambdaQueryWrapper<>();
        if (keyWord != null) {
            queryWrapper.like(ProductInfo::getProductName, keyWord);
        }
        Page<ProductInfo> productInfoPage = productInfoMapper.selectPage(infoPage, queryWrapper);
        return getSellerProductInfoListVo(productInfoPage);
    }

    @Override
    public SellerProductInfoListVo sellerProductInfoVoByCategoryType(Integer categoryType, Integer page, Integer size) {
        Page<ProductInfo> infoPage = new Page<>(page, size);
        LambdaQueryWrapper<ProductInfo> queryWrapper = new LambdaQueryWrapper<>();
        if (categoryType != null) {
            queryWrapper.eq(ProductInfo::getCategoryType, categoryType);
        }
        Page<ProductInfo> productInfoPage = productInfoMapper.selectPage(infoPage, queryWrapper);
        return getSellerProductInfoListVo(productInfoPage);
    }

    @Override
    public SellerProductInfoMapVo sellerProductInfoVoById(Integer id) {
        ProductInfo productInfo = productInfoMapper.selectById(id);
        SellerProductInfoMapVo infoMapVo = new SellerProductInfoMapVo();
        infoMapVo.setStatus(productInfo.getProductStatus() == 1);
        infoMapVo.setId(productInfo.getProductId());
        infoMapVo.setName(productInfo.getProductName());
        infoMapVo.setPrice(productInfo.getProductPrice());
        infoMapVo.setStock(productInfo.getProductStock());
        infoMapVo.setDescription(productInfo.getProductDescription());
        infoMapVo.setIcon(productInfo.getProductIcon());
        Map<String, Integer> map = new HashMap<>();
        map.put("categoryType", productInfo.getCategoryType());
        infoMapVo.setCategory(map);
        return infoMapVo;
    }

    @Override
    public List<ProductExcelVo> excelList() {
        List<ProductInfo> productInfoList = productInfoMapper.selectList(null);
        List<ProductExcelVo> productExcelVoList = new ArrayList<>();
        for (ProductInfo productInfo : productInfoList) {
            ProductExcelVo productExcelVo = new ProductExcelVo();
            BeanUtils.copyProperties(productInfo, productExcelVo);
            if (productInfo.getProductStatus() == 1) {
                productExcelVo.setProductStatus("上架");
            } else {
                productExcelVo.setProductStatus("下架");
            }
            productExcelVo.setCategoryName(productCategoryMapper.findCategoryNameByType(productInfo.getCategoryType()));


            productExcelVoList.add(productExcelVo);
        }

        return null;
    }

    @Override
    public List<ProductInfo> excelToProductInfoList(InputStream inputStream) {
        try {
            List<ProductInfo> list = new ArrayList<>();
            EasyExcel.read(inputStream)
                    .head(ProductExcelVo.class)
                    .sheet()
                    .registerReadListener(new AnalysisEventListener<ProductExcelVo>() {

                        @Override
                        public void invoke(ProductExcelVo excelData, AnalysisContext analysisContext) {
                            ProductInfo productInfo = new ProductInfo();
                            BeanUtils.copyProperties(excelData, productInfo);
                            if (excelData.getProductStatus().equals("正常")) {
                                productInfo.setProductStatus(1);
                            } else {
                                productInfo.setProductStatus(0);
                            }
                            list.add(productInfo);
                        }

                        @Override
                        public void doAfterAllAnalysed(AnalysisContext analysisContext) {
                            log.info("=========================文件解析完成=========================");
                        }
                    }).doRead();
            return list;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }


    private SellerProductInfoListVo getSellerProductInfoListVo(Page<ProductInfo> productInfoPage) {
        SellerProductInfoListVo infoListVo = new SellerProductInfoListVo();
        infoListVo.setSize(productInfoPage.getSize());
        infoListVo.setTotal(productInfoPage.getTotal());
        List<ProductInfo> records = productInfoPage.getRecords();
        List<SellerProductInfoVo> recordsVo = new ArrayList<>();

        for (ProductInfo record : records) {
            SellerProductInfoVo infoVo = new SellerProductInfoVo();
            infoVo.setStock(record.getProductStock());
            infoVo.setStatus(record.getProductStatus() == 1);
            infoVo.setId(record.getProductId());
            infoVo.setName(record.getProductName());
            infoVo.setPrice(record.getProductPrice());
            infoVo.setIcon(record.getProductIcon());
            infoVo.setDescription(record.getProductDescription());
            LambdaQueryWrapper<ProductCategory> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(ProductCategory::getCategoryType, record.getCategoryType());
            ProductCategory productCategory = productCategoryMapper.selectOne(queryWrapper);
            infoVo.setCategoryName(productCategory.getCategoryName());
            recordsVo.add(infoVo);
        }
        infoListVo.setContent(recordsVo);
        return infoListVo;
    }
}
